{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 用GUI 自动化控制键盘和鼠标  \n",
    "pyautogui模块可以向Windows、OS X 和Linux 发送虚拟按键和鼠标点击。根据使用的操作系统，在安装pyautogui之前，可能需要安装一些其他模块。\n",
    "+ Windows: 不需要安装其他模块。\n",
    "+ OS X:\n",
    "```\n",
    "sudo pip3 install pyobjc-framework-Quartz\n",
    "sudo pip3 install pyobjc-core\n",
    "sudo pip3 install pyobjc\n",
    "```\n",
    "+ Linux:\n",
    "```\n",
    "sudo pip3 install python3-xlib\n",
    "sudo apt-get install scrot\n",
    "sudo apt-get install python3-tk\n",
    "sudo apt-get install python3-dev\n",
    "```\n",
    "依赖项安装后安装pyautogui：\n",
    "```\n",
    "pip install pyautogui\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用pyautogui需要注意防止或恢复GUI。通过ctrl+cg关闭程序或者。设定暂停和自动防故障，如下：\n",
    "```\n",
    "# 在每次函数调用后等一会儿，将pyautogui.PAUSE 变量设置为要暂停的秒数\n",
    "pyautogui.PAUSE = 1\n",
    "# 设定自动防故障\n",
    "pyautogui.FAILSAFE = True\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "常用函数如下：\n",
    "\n",
    "|函数|用途|\n",
    "|-|-|\n",
    "|moveTo(x，y,duration)|将鼠标移动到指定的x、y 坐标，duration每次移动耗时多少秒，如果没有数调用duration，鼠标就会马上从一个点移到另一个点|\n",
    "|moveRel(xOffset，yOffset,duration)|相对于当前位置移动鼠标|\n",
    "|pyautogui.position()|确定鼠标当前位置|\n",
    "|dragTo(x，y,duration)|按下左键移动鼠标|\n",
    "|dragRel(xOffset，yOffset,duration)|按下左键，相对于当前位置移动鼠标|\n",
    "|click（x，y，button）|模拟点击(默认是左键)|\n",
    "|rightClick() |模拟右键点击|\n",
    "|middleClick()|模拟中键点击|\n",
    "|doubleClick()|模拟左键双击|\n",
    "|pyautogui.scroll(units)|模拟滚动滚轮。正参数表示向上滚动，负参数表示向下滚动|\n",
    "|pyautogui.screenshot()|返回屏幕快照的Image 对象|\n",
    "|pyautogui.pixelMatchesColor(x,y,tuple)|判断x、y 坐标处的像素与指定的颜色是否匹配。第一和第二个参数是xy整数坐标。第三个参数是包含3个整数元组，表示RGB 颜色|\n",
    "|pyautogui.locateOnScreen(image)|将返回图像iamge所在处当前屏幕图像的坐标，如果无法匹配返回None|\n",
    "|pyautogui.center(x,y,w,h)|返回区域的中心坐标|\n",
    "|typewrite(message)|键入给定消息字符串中的字符|\n",
    "|typewrite([key1，key2，key3])|键入给定键字符串，pyautogui.KEYBOARD_KEYS查看键字符串的列表|\n",
    "|press(key)|按下并释放给定键|\n",
    "|keyDown(key)|模拟按下给定键|\n",
    "|keyUp(key)|模拟释放给定键|\n",
    "|mouseDown(x，y，button)|模拟在x、y 处按下指定鼠标按键|\n",
    "|mouseUp(x，y，button)|模拟在x、y 处释放指定键|\n",
    "|hotkey([key1，key2，key3])|模拟按顺序按下给定键字符串，然后以相反的顺序释放|\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2 项目练习  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1 项目：“现在鼠标在哪里？”  \n",
    "在移动鼠标时随时显示 x y 坐标和改点RGB值\n",
    "```\n",
    "# 显示鼠标实时位置\n",
    "import pyautogui\n",
    "\n",
    "# 程序终止crtl+c\n",
    "print('Press Ctrl-C to quit.')\n",
    "\n",
    "try:\n",
    "    while True:\n",
    "        x, y = pyautogui.position()\n",
    "        positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4)\n",
    "        # 获得当前点的颜色\n",
    "        pixelColor = pyautogui.screenshot().getpixel((x, y))\n",
    "        positionStr += ' RGB: (' + str(pixelColor[0]).rjust(3)\n",
    "        positionStr += ', ' + str(pixelColor[1]).rjust(3)\n",
    "        positionStr += ', ' + str(pixelColor[2]).rjust(3) + ')'\n",
    "        # end结尾添加的字符，默认换行符\n",
    "        print(positionStr, end='')\n",
    "        # https://blog.csdn.net/lucosax/article/details/34963593\n",
    "        # 得到了许多\\b 字符构成的字符串，长度与positionStr中保存的字符串长度一样，效果就是擦除了前面打印的字符串\\\n",
    "        # flush把文件从内存buffer（缓冲区）中强制刷新到硬盘中，同时清空缓冲区。实现动态效果\n",
    "        print('\\b' * len(positionStr), end='', flush=True)\n",
    "\n",
    "# 退出程序\n",
    "except KeyboardInterrupt:\n",
    "    print('\\nDone.')\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 项目：自动填表程序  \n",
    "实现自动填表，表格网站，地址http://autbor.com/form\n",
    "```python\n",
    "import pyautogui, time\n",
    "# Set these to the correct coordinates for your computer\n",
    "# name输入位置\n",
    "nameField = (622, 199)\n",
    "submitButton = (601, 978)\n",
    "submitButtonColor = (31, 115, 230)\n",
    "submitAnotherLink = (760, 224)\n",
    "\n",
    "# 表单数据\n",
    "formData = [{'name': 'Alice', 'fear': 'eavesdroppers', 'source': 'wand','robocop': 4, 'comments': 'Tell Bob I said hi.'},\n",
    "            {'name': 'Bob', 'fear': 'bees', 'source': 'amulet', 'robocop': 4,'comments': 'Please take the puppets out of the break room.'},\n",
    "            {'name': 'Carol', 'fear': 'puppets', 'source': 'crystal ball','robocop': 1, 'comments': 'Please take the puppets out of the break room.'},\n",
    "            {'name': 'Alex Murphy', 'fear': 'ED-209', 'source': 'money','robocop': 5, 'comments': 'Protect the innocent. Serve the publictrust. Uphold the law.'},]\n",
    "\n",
    "# 暂停0.5s\n",
    "pyautogui.PAUSE = 0.5\n",
    "for person in formData:\n",
    "    # Give the user a chance to kill the script.\n",
    "    print('>>> 5 SECOND PAUSE TO LET USER PRESS CTRL-C <<<')\n",
    "    time.sleep(5)\n",
    "    # Wait until the form page has loaded.\n",
    "    # 判断点submitButton和submitButtonColor的颜色是否匹配\n",
    "    while not pyautogui.pixelMatchesColor(submitButton[0], submitButton[1],submitButtonColor):\n",
    "        time.sleep(0.5)\n",
    "    print('Entering %s info...' % (person['name']))\n",
    "        \n",
    "    # 从名字开始填写\n",
    "    pyautogui.click(nameField[0], nameField[1])\n",
    "    # Fill out the Name field.\n",
    "    pyautogui.typewrite(person['name'] + '\\t')\n",
    "    # Fill out the Greatest Fear(s) field.\n",
    "    pyautogui.typewrite(person['fear'] + '\\t')\n",
    "    \n",
    "    # Fill out the Source of Wizard Powers field.\n",
    "    if person['source'] == 'wand':\n",
    "        # 按下键\n",
    "        pyautogui.typewrite(['down'])\n",
    "        # 回车\n",
    "        pyautogui.typewrite(['enter'])\n",
    "        # tab\n",
    "        pyautogui.typewrite(['\\t'])\n",
    "    elif person['source'] == 'amulet':\n",
    "        pyautogui.typewrite(['down', 'down'])\n",
    "        pyautogui.typewrite(['enter'])\n",
    "        pyautogui.typewrite(['\\t'])\n",
    "    elif person['source'] == 'crystal ball':\n",
    "        pyautogui.typewrite(['down', 'down', 'down'])\n",
    "        pyautogui.typewrite(['enter'])\n",
    "        pyautogui.typewrite(['\\t'])\n",
    "    elif person['source'] == 'money':\n",
    "        pyautogui.typewrite(['down', 'down', 'down', 'down'])\n",
    "        pyautogui.typewrite(['enter'])\n",
    "        pyautogui.typewrite(['\\t'])\n",
    "    # Fill out the RoboCop field.\n",
    "    if person['robocop'] == 1:\n",
    "        pyautogui.typewrite([' ', '\\t'])\n",
    "    elif person['robocop'] == 2:\n",
    "        pyautogui.typewrite(['right', '\\t'])\n",
    "    elif person['robocop'] == 3:\n",
    "        pyautogui.typewrite(['right', 'right', '\\t'])\n",
    "    elif person['robocop'] == 4:\n",
    "        pyautogui.typewrite(['right', 'right', 'right', '\\t'])\n",
    "    elif person['robocop'] == 5:\n",
    "        pyautogui.typewrite(['right', 'right', 'right', 'right', '\\t'])\n",
    "        \n",
    "    # Fill out the Additional Comments field.\n",
    "    # 输入文字\n",
    "    pyautogui.typewrite(person['comments'] + '\\t')\n",
    "    # Click Submit.\n",
    "    #pyautogui.press('enter')\n",
    "    # Wait until form page has loaded.\n",
    "    print('Clicked Submit.')\n",
    "    time.sleep(5)\n",
    "    # Click the Submit another response link.\n",
    "    # 确认提交\n",
    "    pyautogui.click(submitAnotherLink[0], submitAnotherLink[1])\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 参考链接\n",
    "+ 完整pyautogui文档 https://pyautogui.readthedocs.io/en/latest/\n",
    "+ https://www.jianshu.com/p/41463c82ec8f\n",
    "+ https://blog.csdn.net/yzy_1996/article/details/85244714"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
